import { Emitter } from '../../utils';

import {
  IPtyExitEvent,
  ITerminalController,
  ITerminalError,
  ITerminalErrorService,
  ITerminalGroupViewService,
  ITerminalService,
} from '../common';

export class TerminalErrorService implements ITerminalErrorService {
  // 终端错误集合，key 为终端 id
  errors: Map<string, ITerminalError> = new Map();

  // 错误变更事件
  protected _onErrorsChangeEmitter = new Emitter<void>();
  onErrorsChange = this._onErrorsChangeEmitter.event;

  private service: ITerminalService;
  private controller: ITerminalController;
  private view: ITerminalGroupViewService;

  constructor(
    service: ITerminalService,
    controller: ITerminalController,
    view: ITerminalGroupViewService
  ) {
    this.service = service;
    this.controller = controller;
    this.view = view;

    // 监听终端服务的错误事件，记录错误并触发变更事件
    this.service.onError((error) => {
      this.errors.set(error.id, error);
      this._onErrorsChangeEmitter.fire();
    });

    // 监听终端退出事件，非复用终端则移除对应 widget
    this.service.onExit((event: IPtyExitEvent) => {
      try {
        const widget = this.view.getWidget(event.sessionId);
        if (!widget.reuse) {
          this.view.removeWidget(event.sessionId);
        }
      } catch (_e) {
        /** nothing */
      }
    });

    // 监听终端关闭事件，移除错误并触发变更事件
    this.controller.onDidCloseTerminal((e) => {
      this.errors.delete(e.id);
      this._onErrorsChangeEmitter.fire();
    });
  }

  /**
   * 修复指定终端客户端的错误
   * @param clientId 终端客户端 id
   */
  async fix(clientId: string) {
    const client = this.controller.findClientFromWidgetId(clientId);
    if (client) {
      await 0; // 使后面的 delete 发生在下一个 microTask 中，避免在迭代过程中修改 this.errors
      this.errors.delete(clientId);
      this._onErrorsChangeEmitter.fire();

      client.reset();
      return client.attached.promise;
    }
  }
}
